package cn.edu.neu.vmmigeval;

import cn.edu.neu.vmmigeval.cloud.config.Migration;
import cn.edu.neu.vmmigeval.cloud.entity.DataCenter;
import cn.edu.neu.vmmigeval.cloud.entity.DataCenterBroker;
import cn.edu.neu.vmmigeval.cloud.config.CloudletRegistry;
import cn.edu.neu.vmmigeval.cloud.policy.VmAllocation;
import cn.edu.neu.vmmigeval.cloud.util.HostUtil;
import cn.edu.neu.vmmigeval.evaluation.PDM;
import cn.edu.neu.vmmigeval.evaluation.PowerModel;
import cn.edu.neu.vmmigeval.evaluation.SLAViolation;
import cn.edu.neu.vmmigeval.evaluation.VmMigrationCost;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The simulation entry.
 * <p>
 * Created by yfwz100 on 16/2/25.
 */
public class Simulation {

    public static void main(String[] args) {
        Simulation simulation = new Simulation();
        simulation.rerun();
    }

    void runOneTime(String scale, String workloadType, String strategyName) {
        //--------------------------start init--------------------------
        CaseBuilder it = new CaseBuilder();
        DataCenter datacenter = it.initHosts(scale, workloadType);
        DataCenterBroker broker = it.initVms(datacenter);
        CloudletRegistry clr = it.getCloudletRegistry(datacenter);
        int cloudletIds = it.initCloudlets(datacenter, broker, clr);
        int clock = 0;
        //--------------------------end init--------------------------

        // datacenter.setVmAllocation(new VmAllocation());
        //DatacenterUtil.printTwoHostsChange(0,datacenter);
        //如果需要的时候可以直接重新启用该方法
        //DatacenterUtil.writeMappingToFile(datacenter);
        double threshold = 0.9;
        //default
//			 datacenter.setVmAllocation(new VmAllocation(new MigratedHostPolicyInterQuartileRange(),
//					 new VmSelectionPolicyDefault(threshold),new VmPlacementPolicyDefault(threshold)));
//			 name = "MigratedHostPolicyInterQuartileRange";
        VmAllocation vmAllocation = HostUtil.getVmAllocation(strategyName, threshold, datacenter);
        datacenter.setVmAllocation(vmAllocation);
        List<Integer> pdh = new ArrayList<Integer>();
        List<Double> pdv = new ArrayList<Double>();
        Map<Integer, List<Double>> mapCld = new HashMap<Integer, List<Double>>();
        double totalEnergy = 0.0;
        //DatacenterUtil.printDatacenterHosts(datacenter);
        // String url = "C:\\Users\\206\\Desktop\\data\\" +datacenter.getScale()+"\\"+datacenter.getWorkloadType()+"\\"+name+"\\";
        String url = System.getProperty("user.dir") + "\\" + "name" + "\\";
        //C:\\Users\\206\\Desktop\\mapping
        for (clock = 1; clock < 1001; clock++) {
            //更新一个周期
            System.out.println("执行第" + clock + "个周期");
            datacenter.updateAllMigration();
            broker.updateVmsProcessing(clock);
            datacenter.updateHostsProcessing(clock);
                 /*
				  * PDH
				  */
            SLAViolation sla = new SLAViolation();
            Integer slasOfThisClock = sla.getSLAViolations(datacenter.getHosts());
            pdh.add(slasOfThisClock);
            //监控
            datacenter.vmAllocation.optimizeAllocation(datacenter, clock);
            List<Migration> migs = datacenter.vmAllocation.getMigrations();
                    //能耗
            PowerModel pm = new PowerModel();
            totalEnergy += pm.getPower(clock, datacenter, url, strategyName);
            //云任务
            // CloudResponse cr = new CloudResponse();
            //mapCld.put(clock, cr.getCloudResponseTimes(clock, broker));
            //overCld.add(cr.getCloudResponseTimes(clock, broker));
				 /*
				  * PDV
				  */
            VmMigrationCost mc = new VmMigrationCost();
            Double costsOfThisClock = mc.getMigrationCost(migs, broker.getVms().size());
            pdv.add(costsOfThisClock);
            //DatacenterUtil.printTwoHostsChange(clock,datacenter);
            // DatacenterUtil.printCloudlets(broker);

            //if(clock%40<20){
            cloudletIds = InitDatacenter.addCloudlets(cloudletIds, broker, clr, clock, scale);
            //}
        }
        // System.out.println("迁移次数："+datacenter.getMigrationFinished().size());
        // DatacenterUtil.printFinishedCloudlets(broker);

        PDM.writePDMtoFile(totalEnergy, url, broker, datacenter, pdh, pdv);
    }

    public void rerun() {
        String[] scales = {"big"};//"middle","small",
        String[] workloadTypes = {"cpu"};//,cpu "ram","bw","disk"
        String[] names = {
                "OFIF",
                "IMP",
                "DTDT",
                "MGRDSM"
        };
        int i = 0;
        for (String scale : scales) {
            for (String workloadType : workloadTypes) {
                for (String name : names) {
                    System.out.println("+++++++++++++++第 +" + i + "个周期++++++++++++++++++");
                    runOneTime(scale, workloadType, name);
                    i++;
                }
            }
        }
    }
}
